﻿using MetroDataQuery.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MetroDataQuery.Utility
{
    public class UpdateMonitorPointQuery
    {



        /// <summary>
        /// 生成更新观测值表的sql
        /// </summary>
        /// <param name="prjId">工程id</param>
        /// <param name="ptName">点名</param>
        /// <param name="value">测值</param>
        /// <param name="dateStr">时间</param>
        /// <returns></returns>
        private static string GenerateUpdateString(int prjId, string ptName, double value, string dateStr, bool review = false)
        {
            var dictInfo = PointsDictionaryQuery.GetDictPointByName(prjId, ptName);
            if (dictInfo == null) return "";

            var table = MetroDataBaseUtility.GetTableNameByMonitorType(prjId, dictInfo.MonitorType, false);

            var deleteSql = string.Format("delete from {0} where PrjId={1} and DateTime='{2}' and Name='{3}';"
                , table, prjId, dateStr, ptName);
            var sql = String.Format("insert into {0} (PrjId,Name,Value,DateTime) VALUES ({1},'{2}',{3},'{4}');", table,
                prjId, ptName, value, dateStr);
            //计算累积变化
            var changeSql = UpdateMonitorPointQuery.GenerateUpdateResultString(prjId, ptName, value, dateStr, table, review);
            return string.Concat(changeSql, deleteSql, sql);
        }



        /// <summary>
        /// 对一个点,获取累计值更新的sql
        /// </summary>
        /// <param name="prjId">项目编号</param>
        /// <param name="ptName">点号</param>
        /// <param name="value">测值</param>
        /// <param name="dateStr">时间</param>
        /// <param name="tableName">观测值所在的表名</param>
        /// <param name="review">是否是要审核</param>
        /// <returns></returns>
        private static string GenerateUpdateResultString(int prjId, string ptName, double value,
            string dateStr, string tableName, bool review = false)
        {
            try
            {
                using (var db = new MonitorProjectsEntities())
                {
                    var time = DateTime.Parse(dateStr);
                    var changeValue = db.MonitorPointChangeLog.
                            Where(p => p.PrjId == prjId && p.PointName == ptName && p.DateTime <= time)
                            .Select(p => p.ChangeValue).DefaultIfEmpty(0).Sum();
                    //初始值                    
                    var originPt = MonitorPointsQuery.GetOrigin(prjId, tableName, ptName);
                    //计算变化量,如果originPt为null,说明上传的是初始值
                    value = originPt == null ? 0.0 : (value + changeValue - originPt.Value.Value) * 1000;
                    //如果没有初始值,默认不审核
                    if (originPt == null) review = false;
                    value = Math.Round(value, 2);
                    if (review == false)//不审核
                    {
                        //累积变化TableName
                        var resultTable = tableName.Replace("Points", "ResultPoints");
                        var deleteSql = string.Format("delete from {0} where PrjId={1} and DateTime='{2}' and Name='{3}';"
                            , resultTable, prjId, dateStr, ptName);
                        var sql = String.Format("insert into {0} (PrjId,Name,Value,DateTime) VALUES ({1},'{2}',{3},'{4}');", resultTable,
                            prjId, ptName, value, dateStr);

                        return string.Concat(deleteSql, sql);
                    }
                    else//审核
                    {
                        using (var prjDb = new MetroProjectsEntities())
                        {
                            var date = DateTime.Parse(dateStr);
                            var pt = new PreReviewMonitorPoints()
                            {
                                DateTime = date,
                                Name = ptName,
                                Value = value,
                                PrjId = prjId
                            };
                            var exsit = prjDb.PreReviewMonitorPoints.Where(p => p.PrjId == prjId && p.DateTime == date && p.Name == ptName);
                            prjDb.PreReviewMonitorPoints.RemoveRange(exsit);
                            prjDb.PreReviewMonitorPoints.Add(pt);
                            prjDb.SaveChanges();
                            return string.Empty;
                        }
                    }

                }
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 上传监测数据,覆盖已有数据
        /// </summary>
        /// <param name="prjId">编号</param>
        /// <param name="dateStr">时间</param>
        /// <param name="names">点号的数组列表</param>
        /// <param name="values">测值的数组列表</param>
        public static void UpdatePoints(int prjId, string dateStr, string[] names, double[] values, bool[] reviews = null)
        {
            var sql = "";
            for (var i = 0; i < names.Length; i++)
            {
                sql += UpdateMonitorPointQuery.GenerateUpdateString(prjId, names[i].Trim(), values[i], dateStr,
                    reviews != null ? reviews[i] : false);
            }
            if (sql == string.Empty) return;
            using (var db = new MonitorProjectsEntities())
            {
                db.Database.ExecuteSqlCommand(sql);
            }
            UpdateMonitorPointQuery.GenerateReviewSummary(prjId, dateStr, names, reviews);
        }


        private static void GenerateReviewSummary(int prjId, string dateStr, string[] names, bool[] reviews)
        {
            if (reviews == null) return;
            var reviewItems = names.Zip(reviews, (a, b) => new
            {
                name = a,
                review = b
            }).Where(p => p.review == true).ToList();

            if (reviewItems.Count == 0) return;

            using (var db = new MetroProjectsEntities())
            {
                var time = DateTime.Parse(dateStr);

                var summary = (from p in reviewItems
                               join q in db.MonitorPointsDictionary.Where(p => p.PrjId == prjId)
                                   on p.name equals q.Name
                                   into gs
                               from g in gs.DefaultIfEmpty()
                               where g != null && g.Name == p.name
                               group g by new { g.MonitorType, g.Location }
                                   into gg
                                   select new
                                   {
                                       DateTime = time,
                                       Location = gg.Key.Location,
                                       MonitorType = gg.Key.MonitorType,
                                       PrjId = prjId
                                   }).ToList();

                var summaryList = from p in summary
                                  select new PointsSummaryNeedToBeReviewed()
                                  {
                                      DateTime = p.DateTime,
                                      Location = p.Location,
                                      MonitorType = p.MonitorType,
                                      PrjId = prjId
                                  };
                foreach (var item in summaryList)
                {
                    if (db.PointsSummaryNeedToBeReviewed.SingleOrDefault(p => p.PrjId == item.PrjId && p.DateTime == item.DateTime
                        && p.Location == item.Location && p.MonitorType == item.MonitorType) == null)
                    {
                        db.PointsSummaryNeedToBeReviewed.Add(item);
                    }
                }
                db.SaveChanges();
            }
        }




    }

}
